<?php

 /**
  * @package JooS
  * @subpackage PHPackager
  */

  require_once "JooS/PHPackager/DOM/Node/Interface.php";

  abstract class JooS_PHPackager_DOM_Node implements JooS_PHPackager_DOM_Node_Interface {
    /**
     * @var DOMNode
     */
    private $_DOMNode = null;

    /**
     * @var DOMNode
     */
    private $_parentNode = null;

    /**
     *
     * @param DOMNode $DOMNode
     * @param JooS_PHPackager_DOM_Node $parentNode
     */
    protected function __construct($DOMNode, JooS_PHPackager_DOM_Node $parentNode = null) {
      $this->_DOMNode = $DOMNode;
      $this->_parentNode = $parentNode;
    }

    /**
     *
     * @param DOMNode $DOMNode
     * @param JooS_PHPackager_DOM_Node $parentNode
     * @param string $className
     * @return JooS_PHPackager_DOM_Node
     */
    public static function newInstance(DOMNode $DOMNode, JooS_PHPackager_DOM_Node $parentNode = null, $className = null) {
      require_once "JooS/Loader.php";

      switch (true) {
        case (!!$className):
          break;
        case ($DOMNode->nodeType == XML_ELEMENT_NODE):
          $className = JooS_Loader::getClassName("JooS_PHPackager_DOM_Element", $DOMNode->nodeName, true);
          break;
        case ($DOMNode->nodeType == XML_PI_NODE):
          $className = JooS_Loader::getClassName("JooS_PHPackager_DOM_ProcessingInstruction", $DOMNode->nodeName, true);
          break;
      }

      $_instance = null;
      if (!is_null($className) && JooS_Loader::loadClass($className)) {
        $_instance = new $className($DOMNode, $parentNode);
      }
      return $_instance;
    }

    /**
     * @param string $source
     * @param JooS_Syntax_Abstract $syntaxLanguage
     * @return string
     */
    protected function compileSource($source, JooS_Syntax_Abstract $syntaxLanguage) {
      require_once "JooS/Syntax/Compiler.php";
      return JooS_Syntax_Compiler::newInstance($syntaxLanguage)->compile($source);
    }

    /**
     * @return DOMNode
     */
    public function getNode() {
      return $this->_DOMNode;
    }

    /**
     * @return DOMNode
     */
    public function getParent() {
      return $this->_parentNode;
    }
  }
